package com.bocloud.cmp.driver.providers.os;

import java.util.List;

import org.openstack4j.api.Builders;
import org.openstack4j.api.exceptions.ClientResponseException;
import org.openstack4j.model.common.ActionResponse;
import org.openstack4j.model.network.Network;
import org.openstack4j.model.network.NetworkType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bocloud.cmp.driver.convertor.BeanConvert;
import com.bocloud.cmp.driver.convertor.os.ConvertNetworks;
import com.bocloud.cmp.driver.providers.NetworkDriver;
import com.bocloud.cmp.model.NetworkModel;
import com.bocloud.cmp.model.SwitchModel;
import com.bocloud.common.model.BsmResult;
import com.google.common.collect.Lists;

public class OSNetworkDriver extends OSDriver implements NetworkDriver {

    private static final Logger logger = LoggerFactory.getLogger(OSNetworkDriver.class);

    public OSNetworkDriver() {
        super();
    }

    public OSNetworkDriver(String endpoint, String username, String password, String tenant, String domain,
            String project, Version version) {
        super(endpoint, username, password, tenant, domain, project, version);
    }

    @Override
    public BsmResult list() {
        List<NetworkModel> models = Lists.newArrayList();
        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        List<? extends Network> networks = this.getClient().networking().network().list();
        if (null != networks) {
            BeanConvert<NetworkModel, Network> convertNetworks = new ConvertNetworks();
            for (Network network : networks) {
                models.add(convertNetworks.convertModel(network));
            }
        }

        return new BsmResult(true, models, "success");
    }

    @Override
    public BsmResult create(NetworkModel model) {
        // Tenant tenant = null;
        Network network = null;
        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }

        Network networkBuilder = buildNetwork(model);
        if (null == networkBuilder) {
            return new BsmResult(false, "创建失败！");
        }
        try {
            network = this.getClient().networking().network().create(networkBuilder);
        } catch (ClientResponseException e) {
            if (409 == e.getStatus()) {
                return new BsmResult(false, "段ID已经使用！");
            }
            return new BsmResult(false, "段ID已经使用！");
        }
        if (null == network) {
            return new BsmResult(false, "创建失败！");
        } else {
            BsmResult detail = detail(network.getId());
            if (detail.isSuccess()) {
                return new BsmResult(true, detail.getData(), "create success");
            } else {
                return new BsmResult(false, "创建失败！");
            }
        }
    }

    @Override
    public BsmResult remove(String networkId) {
        ActionResponse response = null;
        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        response = this.getClient().networking().network().delete(networkId);
        if (response.isSuccess()) {
            return new BsmResult(true, "DELETE SUCCESS!");
        } else {
            return new BsmResult(false, response.getFault());
        }
    }

    @Override
    public BsmResult detail(String networkId) {
        Network network = null;
        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        network = this.getClient().networking().network().get(networkId);
        if (null == network) {
            return new BsmResult(false, "network is not exist!");
        } else {
            BeanConvert<NetworkModel, Network> convertNetworks = new ConvertNetworks();
            return new BsmResult(true, convertNetworks.convertModel(network), "success");
        }
    }

    @Override
    public BsmResult modify(NetworkModel model) {
        Network network = null;
        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        network = this.getClient().networking().network().update(model.getNetworkId(), Builders.networkUpdate()
                .name(model.getName()).adminStateUp(model.getAdminStateup()).shared(model.getShared()).build());
        if (null == network) {
            return new BsmResult(false, "修改失败！");
        } else {
            if (network.getName().equals(model.getName())) {
                return new BsmResult(true, "modify success");
            } else {
                return new BsmResult(false, "修改失败！");
            }
        }
    }

    private Network buildNetwork(NetworkModel model) {

        Network networkBuilder = null;
        if (null != model.getPhyNetwork() && null != model.getSegmentationId()) {// vlan
            networkBuilder = Builders.network().name(model.getName()).networkType(NetworkType.forValue(model.getType()))
                    .isRouterExternal(model.getIsRouterExternal()).isShared(model.getShared())
                    .adminStateUp(model.getAdminStateup()).physicalNetwork(model.getPhyNetwork())
                    .segmentId(model.getSegmentationId()).build();
        } else if (null == model.getPhyNetwork() && null == model.getSegmentationId()) {// local
            networkBuilder = Builders.network().name(model.getName()).networkType(NetworkType.forValue(model.getType()))
                    .isRouterExternal(model.getIsRouterExternal()).isShared(model.getShared())
                    .adminStateUp(model.getAdminStateup()).build();
        } else if (null != model.getPhyNetwork() && null == model.getSegmentationId()) {// flat
            networkBuilder = Builders.network().name(model.getName()).networkType(NetworkType.forValue(model.getType()))
                    .isRouterExternal(model.getIsRouterExternal()).isShared(model.getShared())
                    .adminStateUp(model.getAdminStateup()).physicalNetwork(model.getPhyNetwork()).build();

        } else if (null == model.getPhyNetwork() && null != model.getSegmentationId()) {// gre
                                                                                        // vxlan
            networkBuilder = Builders.network().name(model.getName()).networkType(NetworkType.forValue(model.getType()))
                    .isRouterExternal(model.getIsRouterExternal()).isShared(model.getShared())
                    .adminStateUp(model.getAdminStateup()).segmentId(model.getSegmentationId()).build();
        } else {
            return null;
        }

        return networkBuilder;
    }

    @Override
    public BsmResult createDSwitch(SwitchModel switchModel) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public BsmResult createVSwitch(SwitchModel switchModel) {
        // TODO Auto-generated method stub
        return null;
    }
}